package com.example.service.impl;


import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.domain.User;
import com.example.exception.CustomException;
import com.example.mapper.UserMapper;
import com.example.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static com.example.common.enums.ResultCodeEnum.*;


@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Resource
    private UserMapper userMapper;

    @Override
    public String login(User user) {
        User dbUser = userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, user.getUsername()));
        if (ObjectUtil.isNull(dbUser)) {
            throw new CustomException(USER_NOT_EXIST_ERROR);
        }
        boolean checkpw = BCrypt.checkpw(user.getPassword(), dbUser.getPassword());
        if (!checkpw) {
            throw new CustomException(USER_ACCOUNT_ERROR);
        }
        StpUtil.login(dbUser.getId());
        return StpUtil.getTokenValue();
    }

    @Override
    public void register(User user) {
        User regUser = userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, user.getUsername()));
        if (ObjectUtil.isNotNull(regUser)) {
            throw new CustomException(USER_EXIST_ERROR);
        }
        user.setPassword(BCrypt.hashpw(user.getPassword(), BCrypt.gensalt()));
        userMapper.insert(user);
    }

    /*
     * 强制注销 和 踢人下线 的区别在于：
     * 强制注销等价于对方主动调用了注销方法，再次访问会提示：Token无效。
     * 踢人下线不会清除Token信息，而是将其打上特定标记，再次访问会提示：Token已被踢下线。
     * */

    /*
     * 账号封禁
     * 对指定账号进行封禁
     * */
    @Override
    public void disable(Long userId) {
        StpUtil.disable(userId, 86400);
    }

    /*
     * 踢人下线
     * */
    @Override
    public void logout(Long userId) {
        StpUtil.logout(userId);
    }

    /*
     * 强制注销
     * */
    @Override
    public void kickout(Long userId) {
        StpUtil.kickout(userId);
    }

    /*
     * 获取在线用户
     * */
    @Override
    public List<User> onlineUsers() {
        List<String> sessionIdList = StpUtil.searchSessionId("", 0, -1, false);
        List<User> onlineUsers = new ArrayList<>();
        for (String sessionId : sessionIdList) {
            String[] parts = sessionId.split(":");
            String userId = parts[parts.length - 1];
            User user = userMapper.selectById(userId);
            if (ObjectUtil.isNotNull(user)) {
                onlineUsers.add(user);
            }
        }
        return onlineUsers;
    }
}

